﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace p2p.Forms.FileListView
{
    public partial class FileListView : System.Windows.Forms.TreeView
    {
        public FileListView()
        {
            // load the where not really using any Components but we need to Initialize the TreeView Class still
            InitializeComponent();
            // enable the checking for child and parent Checkbox status
            this.AfterCheck += FileListView_AfterCheck;
        }

        protected override void WndProc(ref Message m)
        {
            // Suppress WM_LBUTTONDBLCLK
            if (m.Msg == 0x203) { m.Result = IntPtr.Zero; }
            else base.WndProc(ref m);
        } 
                
        void FileListView_AfterCheck(object sender, TreeViewEventArgs e)
        {
            // check if children are checked
            // set the status of this checked on to all children
            MakeChildStatusMatch(e.Node, e.Node.Checked);

            // check if there is a parent
            if (e.Node.Parent != null)
            {
                // check if parent is checked
                MakeSureParentMatchesChildrenStatus(e.Node.Parent, e.Node.Checked);
            }
        }

        void MakeChildStatusMatch(TreeNode treeNode, bool nodeChecked)
        {
            // make sure that when we're enabling checkboxes we're not firing the event
            preventPropergation();

            foreach (TreeNode node in treeNode.Nodes)
            {
                node.Checked = nodeChecked;
                if (node.Nodes.Count > 0)
                {
                    // If the current node has child nodes, call the CheckAllChildsNodes method recursively.
                    MakeChildStatusMatch(node, nodeChecked);
                }
            }

            // re-enable the event for user clicks
            enablePropergation();
        }

        void MakeSureParentMatchesChildrenStatus(TreeNode treeNode, bool nodeChecked)
        {
            // make sure that when we're enabling checkboxes we're not firing the event
            preventPropergation();

            if (nodeChecked)
            {
                if (!treeNode.Checked)
                    treeNode.Checked = true;
            }
            else
            {
                treeNode.Checked = CheckIfChildIsEnabled(treeNode);
            }

            // re-enable the event for user clicks
            enablePropergation();
        }

        bool CheckIfChildIsEnabled(TreeNode treeNode)
        {
            bool enabled = false;
            foreach (TreeNode tn in treeNode.Nodes)
            {
                if (tn.Nodes.Count > 0)
                {
                    enabled = CheckIfChildIsEnabled(tn);
                }
                else
                {
                    if (tn.Checked)
                        enabled = true;
                }
            }
            return enabled;
        }

        void preventPropergation()
        {
            this.AfterCheck -= FileListView_AfterCheck;
        }

        void enablePropergation()
        {
            this.AfterCheck += FileListView_AfterCheck;
        }

    }
}
